<?php
//=======================================
//###################################
// Kayako Web Solutions
//
// Source Copyright 2001-2004 Kayako Web Solutions
// Unauthorized reproduction is not allowed
// License Number: $%LICENSE%$
// $Author: vshoor $ ($Date: 2007/07/25 06:54:39 $)
// $RCSfile: functions_parserrules.php,v $ : $Revision: 1.12 $ 
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//###################################
//=======================================


if (!defined("INSWIFT")) {
	trigger_error("Unable to process $PHP_SELF", E_USER_ERROR);
}

// Criteria
define("PARSER_SENDERNAME", "sendername");
define("PARSER_SENDEREMAIL", "senderemail");
define("PARSER_DESTINATIONNAME", "destinationname");
define("PARSER_DESTINATIONEMAIL", "destinationemail");
define("PARSER_REPLYTONAME", "replytoname");
define("PARSER_REPLYTOEMAIL", "replytoemail");
define("PARSER_SUBJECT", "subject");
define("PARSER_RECIPIENTS", "recipients");
define("PARSER_BODY", "body");
define("PARSER_BODYSIZE", "bodysize");
define("PARSER_TEXTBODY", "textbody");
define("PARSER_HTMLBODY", "htmlbody");
define("PARSER_TEXTBODYSIZE", "textbodysize");
define("PARSER_HTMLBODYSIZE", "htmlbodysize");
define("PARSER_ATTACHMENTNAME", "attachmentname");
define("PARSER_ATTACHMENTSIZE", "attachmentsize");
define("PARSER_TOTALATTACHMENTSIZE", "totalattachmentsize");
define("PARSER_ISREPLY", "isreply");
define("PARSER_ISTHIRDPARTY", "isthirdparty");
define("PARSER_FLOODPROTECTION", "floodprotection");
define("PARSER_ISSTAFFREPLY", "isstaffreply");
define("PARSER_TICKETSTATUS", "ticketstatus");

// Pre Parse Actions
define("PARSERACTION_FORWARD", "forward");
define("PARSERACTION_REPLY", "reply");
define("PARSERACTION_IGNORE", "ignore");
define("PARSERACTION_NOAUTORESPONDER", "noautoresponder");
define("PARSERACTION_NOALERTRULES", "noalertrules");
define("PARSERACTION_NOTICKET", "noticket");

// Post Parse Actions
define("PARSERACTION_DEPARTMENT", "department");
define("PARSERACTION_OWNER", "owner");
define("PARSERACTION_STATUS", "status");
define("PARSERACTION_PRIORITY", "priority");
define("PARSERACTION_ADDNOTE", "addnote");
define("PARSERACTION_FLAGTICKET", "flagticket");
define("PARSERACTION_SLAPLAN", "slaplan");

define("OP_EQUAL", 1);
define("OP_NOTEQUAL", 2);
define("OP_REGEXP", 3);
define("OP_CONTAINS", 4);
define("OP_NOTCONTAINS", 5);
define("OP_GREATER", 6);
define("OP_LESS", 7);

define("RULE_PREPARSE", 1);
define("RULE_POSTPARSE", 2);

define("RULE_MATCHALL", 1);
define("RULE_MATCHANY", 2);

/**
* Loads the Parser Rules
*/
function loadParserRules()
{
	global $dbCore, $_SWIFT;

	if (isset($_SWIFT["parserrules"]))
	{
		return true;
	}

	$parserrulelist = $parserruleidlist = array();

	// Load Parser Rules
	$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."parserrules` ORDER BY `sortorder` ASC;");
	while ($dbCore->nextRecord())
	{
		$parserruleidlist[] = $dbCore->Record["parserruleid"];
		$parserrulelist[$dbCore->Record["parserruleid"]] = $dbCore->Record;
		$parserrulelist[$dbCore->Record["parserruleid"]]["criteria"] = array();
		$parserrulelist[$dbCore->Record["parserruleid"]]["actions"] = array();
	}

	if (!count($parserruleidlist))
	{
		return false;
	}

	// Load the Criteria
	$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."rulecriteria` WHERE `parserruleid` IN (". buildIN($parserruleidlist) .");");
	while ($dbCore->nextRecord())
	{
		$parserrulelist[$dbCore->Record["parserruleid"]]["criteria"][] = $dbCore->Record;
	}

	// Load the Actions
	$dbCore->query("SELECT * FROM `". TABLE_PREFIX ."ruleactions` WHERE `parserruleid` IN (". buildIN($parserruleidlist) .");");
	while ($dbCore->nextRecord())
	{
		$parserrulelist[$dbCore->Record["parserruleid"]]["actions"][] = $dbCore->Record;
	}

	$_SWIFT["parserrules"] = $parserrulelist;

	return true;
}

/**
* Runs the Parser Rules
*/
function runParserRules(&$email, &$ticketobj)
{
	global $dbCore, $_SWIFT;

	$_rules = &$_SWIFT["parserrules"];
	$_ruleactionidlist = array();

	if (!_is_array($_rules))
	{
		return false;
	}

	foreach ($_rules as $rulekey=>$ruleval)
	{
		if (!count($ruleval["criteria"]))
		{
			continue;
		}
		$criteriaall = $criteriaany = $rulematched = false;
		$prevresult = true;

		// Itterate through criteria
		foreach ($ruleval["criteria"] as $ckey=>$cval)
		{
			$result = false;

			switch ($cval["name"])
			{
				case PARSER_SENDERNAME:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["fromNameRule"]);
					break;

				case PARSER_SENDEREMAIL:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["fromEmailRule"]);
					break;

				case PARSER_DESTINATIONNAME:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["toName"]);
					break;

				case PARSER_DESTINATIONEMAIL:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["toEmail"]);
					break;

				case PARSER_REPLYTONAME:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["replytoName"]);
					break;

				case PARSER_REPLYTOEMAIL:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["replytoEmail"]);
					break;

				case PARSER_SUBJECT:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["subject"]);
					break;

				case PARSER_RECIPIENTS:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["recipients"]);
					break;

				case PARSER_BODY:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["finalContent"]);
					break;

				case PARSER_BODYSIZE:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], strlen($email["finalContent"]));
					break;

				case PARSER_TEXTBODY:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["text"]);
					break;

				case PARSER_HTMLBODY:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["html"]);
					break;

				case PARSER_TEXTBODYSIZE:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], strlen($email["text"]));
					break;

				case PARSER_HTMLBODYSIZE:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], strlen($email["html"]));
					break;

				case PARSER_ATTACHMENTNAME:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["attachmentNames"]);
					break;

				case PARSER_ATTACHMENTSIZE:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["attachmentSizes"]);
					break;

				case PARSER_TOTALATTACHMENTSIZE:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["totalAttachmentSize"]);
					break;

				case PARSER_ISREPLY:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["isticketreply"]);
					break;

				case PARSER_ISTHIRDPARTY:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["isthirdparty"]);
					break;

				case PARSER_FLOODPROTECTION:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["floodprotection"]);
					break;

				case PARSER_ISSTAFFREPLY:
					$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $email["isstaffreply"]);
					break;

				case PARSER_TICKETSTATUS:
					if (is_object($ticketobj) && $ticketobj->ticket)
					{
						$result = checkRuleCriteria($cval["ruleop"], $cval["rulematch"], $ticketobj->ticket["ticketstatusid"]);
					}
					break;
			}

			if ($result == true)
			{
				$criteriaany = true;
			}

			// break right here if our criteria is to match just one rule
			if ($result == true && $ruleval["matchtype"] == RULE_MATCHANY)
			{
				break;
			}

			// Otherwise we check all criterias
			if ($result == true && $prevresult == true)
			{
				$criteriaall = true;
			} else {
				$criteriaall = false;
			}

			$prevresult = $result;
		}

		if ($ruleval["matchtype"] == RULE_MATCHANY && $criteriaany == true)
		{
			$rulematched = true;
		} else if ($ruleval["matchtype"] == RULE_MATCHALL && $criteriaall == true) {
			$rulematched = true;
		}

		if ($rulematched)
		{
			$_ruleactionidlist[] = $ruleval["parserruleid"];
			if ($ruleval["stopprocessing"] == 1)
			{
				// Stop Processing the loop right here
				break;
			}
		}
	}

	return $_ruleactionidlist;
}

/**
* Get the queue return email address
*/
function getQueueReturnEmail($emailqueueid)
{
	global $_SWIFT;

	if (!isset($_SWIFT["queuecache"]["list"][$emailqueueid]))
	{
		return $_SWIFT["settings"]["general_returnemail"];
	}

	$_queue = $_SWIFT["queuecache"]["list"][$emailqueueid];
	if (!empty($_queue["customfromemail"]))
	{
		return $_queue["customfromemail"];
	}

	return $_queue["email"];
}

/**
* Get the queue return name
*/
function getQueueReturnName($emailqueueid)
{
	global $_SWIFT;

	if (!isset($_SWIFT["queuecache"]["list"][$emailqueueid]))
	{
		return "";
	}

	$_queue = $_SWIFT["queuecache"]["list"][$emailqueueid];
	if (!empty($_queue["customfromname"]))
	{
		return $_queue["customfromname"];
	}

	return "";
}

/**
* Sends a reply to client
*/
function actionSendReply(&$email, $subject, $contents)
{
	global $_SWIFT;

	// If From Email is added as queue then ignore.. OR if flood protection is triggered
	if (in_array(strtolower($email["fromEmail"]), $_SWIFT["queuecache"]["p"]) || $email["floodprotection"] == true)
	{
		return false;
	}

	require_once ("./includes/functions_mail.php");
	$mailObj = new SWIFT_Mail();

	if (!empty($email["dispatchsubject"]))
	{
		$mailObj->setSubject($email["dispatchsubject"]);
	} else {
		$mailObj->setSubject($subject);
	}

	$mailObj->setData(getProcessedHTML($contents), getProcessedText($contents));

	$returnemail = getQueueReturnEmail($email["queue"]["emailqueueid"]);
	$returnname = getQueueReturnName($email["queue"]["emailqueueid"]);
	$mailObj->sendMail(array($email["fromEmail"]), $returnemail, $returnname, false);

	return true;
}

/**
* Forwards the mail to another address
*/
function actionSendForward(&$email, $emailto)
{
	global $_SWIFT;

	// If From Email is added as queue then ignore..
	if (in_array(strtolower($email["fromEmail"]), $_SWIFT["queuecache"]["p"]))
	{
		return false;
	}

	require_once ("./includes/functions_mail.php");
	$mailObj = new SWIFT_Mail();

	$mailObj->setSubject($email["subject"]);

	$_htmlcontent = getProcessedHTML($email["finalContent"]);
	$_textcontent = getProcessedText($email["finalContent"]);

	$mailObj->setData($_htmlcontent, $_textcontent);

	$returnemail = $email["fromEmail"];
	$returnname = $email["fromName"];
	$mailObj->sendMail(array($emailto), $returnemail, $returnname, false);

	return true;
}

/**
* Executes the actions for parser rules
*/
function executeParserRuleActions($parserruleidlist, $ruletype, &$email, &$ticketobj)
{
	global $_SWIFT;

	if (!count($parserruleidlist)) // No Parser Rules to execute
	{
		return false;
	}

	$_rules = &$_SWIFT["parserrules"];
	if (!_is_array($_rules))
	{
		return false;
	}

	foreach ($parserruleidlist as $rulekey=>$parserruleid)
	{
		$_rule = &$_rules[$parserruleid];

		if ($_rule["ruletype"] == $ruletype)
		{
			// Carry out all the actions under this rule
			if (!count($_rule["actions"]))
			{
				continue;
			}
			if ($ticketobj)
			{
				$ticketobj->addAuditLogEntry(LOG_PARSER, ACTION_PARSERRULE, sprintf($_SWIFT["language"]["al_prule"], htmlspecialchars($_rule["title"])));
			}

			foreach ($_rule["actions"] as $actionkey=>$_action)
			{
				switch ($_action["name"])
				{
					// Pre Parse Rules
					case PARSERACTION_IGNORE:
						$email["ignore"] = true;
						break;
					case PARSERACTION_NOAUTORESPONDER:
						$email["noautoresponder"] = true;
						break;
					case PARSERACTION_NOALERTRULES:
						$email["noalertrules"] = true;
						break;
					case PARSERACTION_REPLY:
						actionSendReply($email, $email["subject"], $_action["typedata"]);
						break;
					case PARSERACTION_FORWARD:
						actionSendForward($email, $_action["typechar"]);
						break;
					case PARSERACTION_NOTICKET:
						$email["isticketreply"] = false;
						break;

					// Post Parse Rules
					case PARSERACTION_OWNER:
						if (!is_object($ticketobj))
						{
							return false;
						}
						$ticketobj->assignTicket($_action["typeid"]);
						break;
					case PARSERACTION_PRIORITY:
						if (!is_object($ticketobj))
						{
							return false;
						}
						$ticketobj->changePriority($_action["typeid"]);
						break;
					case PARSERACTION_STATUS:
						if (!is_object($ticketobj))
						{
							return false;
						}
						$ticketobj->changeStatus($_action["typeid"]);
						break;
					case PARSERACTION_DEPARTMENT:
						if (!is_object($ticketobj))
						{
							return false;
						}
						$ticketobj->moveTicket($_action["typeid"]);
						break;
					case PARSERACTION_FLAGTICKET:
						if (!is_object($ticketobj))
						{
							return false;
						}
						$ticketobj->flagTicket($_action["typeid"]);
						break;
					case PARSERACTION_ADDNOTE:
						if (!is_object($ticketobj))
						{
							return false;
						}
						$ticketobj->addTicketNote(NOTE_TICKET, 0, $_action["typedata"]);
						break;
					case PARSERACTION_SLAPLAN:
						if (!is_object($ticketobj))
						{
							return false;
						}
						$ticketobj->resetSLATimeline($_action["typeid"]);
						break;
				}
			}
		}
	}
}

/**
* Checks the criteria using oper and value and returns a bool value
*/
function checkRuleCriteria($oper, $value, $result)
{
	switch ($oper)
	{
		case OP_EQUAL:
			if (is_array($result))
			{
				foreach ($result as $key=>$val)
				{
					if ($value == $val)
					{
						return true;
					}
				}

				return false;
			} else if ($value == $result) {
				return true;
			}

			return false;
			break;

		case OP_NOTEQUAL:
			if (is_array($result))
			{
				$checkres = false;

				foreach ($result as $key=>$val)
				{
					if ($value != $val)
					{
						$checkres = true;
					} else {
						$checkres = false;
					}
				}

				return $checkres;
			} else if ($value != $result) {
				return true;
			}

			return false;
			break;

		case OP_REGEXP:
			if (is_array($result))
			{
				foreach ($result as $key=>$val)
				{
					if (@preg_match($value, $val))
					{
						return true;
					}
				}
			} else if (@preg_match($value, $result)) {
				return true;
			}

			return false;
			break;

		case OP_CONTAINS:
			if (is_array($result))
			{
				foreach ($result as $key=>$val)
				{
					if (@stristr($val, $value))
					{
						return true;
					}
				}
			} else if (@stristr($result, $value)) {
				return true;
			}

			return false;
			break;

		case OP_NOTCONTAINS:
			if (is_array($result))
			{
				$checkres = false;
				foreach ($result as $key=>$val)
				{
					if (!stristr($val, $value))
					{
						$checkres = true;
					} else {
						$checkres = false;
					}
				}

				return $checkres;
			} else if (!stristr($result, $value)) {
				return true;
			}

			return false;
			break;

		case OP_GREATER:
			if (is_array($result))
			{
				foreach ($result as $key=>$val)
				{
					if (intval($val) > intval($value))
					{
						return true;
					}
				}

				return false;
			} else if (intval($result) > intval($value)) {
				return true;
			}

			return false;
			break;

		case OP_LESS:
			if (is_array($result))
			{
				$checkres = false;
				foreach ($result as $key=>$val)
				{
					if (intval($val) < intval($value))
					{
						$checkres = true;
					} else {
						$checkres = false;
					}
				}

				return $checkres;
			} else if (intval($result) < intval($value)) {
				return true;
			}

			return false;
			break;
	}
}
?>